﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Linq.Expressions;
using EfSearchModel;
using EfSearchModel.Model;
using System.Data;

namespace QuickApp.Core
{
    /// <summary>
    /// 用Entity Framework实现仓储模式（Repository）的基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class EFRepository<T> : IRepository<T> where T : class
    {
        // 实体数据集合
        private readonly IDbSet<T> DbSet;

        // 数据库上下文对象
        protected DbContext Context { get; private set; }

        /// <summary>
        /// 构造函数，参数从Ioc获取或者直接传参数
        /// </summary>
        /// <param name="context">数据库上下文对象</param>
        public EFRepository(DbContext context)
        {
            this.Context = context;
            this.DbSet = Context.Set<T>();
        }

        /// <summary>
        /// 添加实体数据
        /// </summary>
        /// <param name="entity">实体数据</param>
        public virtual void Insert(T entity)
        {
            DbSet.Add(entity);
        }

        /// <summary>
        /// 更新实体数据
        /// </summary>
        /// <param name="entity">实体数据</param>
        public virtual void Update(T entity)
        {
            var entryModify = Context.Entry(entity);
            DbSet.Attach(entity);
            entryModify.State = EntityState.Modified;
        }

        /// <summary>
        /// 删除指定Id的实体数据
        /// </summary>
        /// <param name="Id">实体Id</param>
        public virtual void Delete(string Id)
        {
            var entity = DbSet.Find(Id);
            if (entity != null)
            {
                DbSet.Remove(entity);
            }
        }

        /// <summary>
        /// 删除实体数据
        /// </summary>
        /// <param name="entity">实体数据</param>
        public virtual void Delete(T entity)
        {
            if (Context.Entry(entity).State == EntityState.Detached)
            {
                DbSet.Attach(entity);
            }
            DbSet.Remove(entity);
        }

        /// <summary>
        /// 批量删除实体数据
        /// </summary>
        /// <param name="entities">实体数据列表</param>
        public virtual void DeleteAll(IEnumerable<T> entities)
        {
            foreach (T entity in entities)
            {
                Delete(entity);
            }
        }

        /// <summary>
        /// 批量删除指定过滤表达式的实体数据列表
        /// </summary>
        /// <param name="predicate">过滤表达式</param>
        public virtual void DeleteAll(Expression<Func<T, bool>> predicate)
        {
            IEnumerable<T> entities = FindAll(predicate);
            DeleteAll(entities);
        }

        /// <summary>
        /// 获得指定Id的实体数据
        /// </summary>
        /// <param name="Id">实体Id</param>
        /// <returns>数据实体</returns>
        public virtual T Find(string Id)
        {
            return DbSet.Find(Id);
        }

        /// <summary>
        /// 获取指定指定过滤表达式的单个实体数据
        /// </summary>
        /// <param name="predicate">过滤表达式</param>
        /// <returns>数据实体</returns>
        public virtual T Find(Func<T, Boolean> predicate)
        {
            var entity = DbSet.FirstOrDefault(predicate);
            return entity;
        }

        /// <summary>
        /// 获取指定指定过滤表达式的实体数据列表
        /// </summary>
        /// <param name="predicate">过滤表达式</param>
        /// <returns>数据实体列表</returns>
        public virtual IQueryable<T> FindAll(Expression<Func<T, bool>> predicate)
        {
            if (predicate != null)
            {
                return DbSet.Where(predicate).AsNoTracking();
            }
            else
            {
                return DbSet.AsNoTracking();
            }
        }

        /// <summary>
        /// 获取指定搜索条件的数据分页实体
        /// </summary>
        /// <param name="pageInfo">分页信息</param>
        /// <param name="query">搜索条件</param>
        /// <returns>数据分页实体</returns>
        public virtual IPageable<T> GetPageable(PageInfo pageInfo, QueryModel query)
        {
            return new Pageable<T>
            {
                Page = GetPage(pageInfo, query),
                Total = GetTotal(query)
            };
        }

        /// <summary>
        /// 获取指定搜索条件的总记录数
        /// </summary>
        /// <param name="query">搜索条件</param>
        /// <returns></returns>
        protected virtual int GetTotal(QueryModel query)
        {
            return DbSet.Where<T>(query).Count();
        }

        /// <summary>
        /// 获取指定搜索条件的实体数据列表
        /// </summary>
        /// <param name="pageInfo">分页信息</param>
        /// <param name="query">搜索条件</param>
        /// <returns>实体数据列表</returns>
        protected virtual IQueryable<T> GetPage(PageInfo pageInfo, QueryModel query)
        {
            //Context.Configuration.ProxyCreationEnabled = false;

            var page = DbSet.Where(query)
                .OrderUsingSortExpression(pageInfo.SortName + " " + pageInfo.SortOrder)
                .Skip((pageInfo.PageIndex) * pageInfo.PageSize).Take(pageInfo.PageSize).AsNoTracking();

            //DatabaseFactory.Get().Configuration.ProxyCreationEnabled = true;
            return page;
        }
    }
}
